package com.kabigon.tiny.exception.assertion;

import cn.hutool.core.util.ArrayUtil;
import com.kabigon.tiny.exception.BaseException;
import com.kabigon.tiny.exception.WrapException;

import java.text.MessageFormat;
import java.util.function.Supplier;

/**
 * 枚举类型的断言，提供简便的方式判断条件，并在条件满足时抛出异常
 * 错误码和错误信息定义在枚举类中，在本断言方法中，传递错误讯息所需的参数
 * @author xu.biao
 * @version v1.0
 * @Package com.kabigon.tiny.exception
 * @data 2022/5/6 22:55
 */
public interface Assert {

    /**
     * 创建异常
     * @param args
     * @return
     */
    BaseException newException(Object... args);

    /**
     * 创建异常
     * @param cause
     * @param args
     * @return
     */
    BaseException newException(Throwable cause, Object... args);

    /**
     * 创建异常
     * 先使用{@code message}创建异常{@link WrapException},
     * 再以入参的形式传给{@link #newException(Throwable, Object...)},作为最后创建的异常的cause
     * @param message
     * @param args
     * @return
     */
    default BaseException newExceptionWithMsg(String message, Object... args) {
        if (args != null && args.length > 0) {
            message = MessageFormat.format(message, args);
        }

        WrapException e = new WrapException(message);
        throw newException(e, args);
    }

    /**
     * 创建异常
     * 先使用{@code message}创建异常{@link WrapException},
     * 再以入参的形式传给{@link #newException(Throwable, Object...)},作为最后创建的异常的cause
     * @param message
     * @param args
     * @return
     */
    default BaseException newExceptionWithMsg(Throwable throwable, String message, Object... args) {
        if (ArrayUtil.isNotEmpty(args)) {
            message = MessageFormat.format(message, args);
        }

        WrapException e = new WrapException(message, throwable);
        throw newException(e, args);
    }

    /**
     * 断言对象非空，如果对象为空，则抛出异常
     * @param obj 带判断对象
     */
    default void assertNotNull(Object obj) {
        if (obj == null) {
            throw newException();
        }
    }

    /**
     * 断言对象非空，如果对象为空，则抛出异常
     * 异常信息支持参数传递，避免在判断前进行字符串拼接
     * @param obj 带判断对象
     * @param args 异常信息参数（message占位符对应的参数列表）
     */
    default void assertNotNull(Object obj, Object... args) {
        if (obj == null) {
            throw newException(args);
        }
    }

    /**
     * 断言对象非空，如果对象为空，则抛出异常
     *
     * @param obj 带判断对象
     * @param errMsg 自定义异常信息
     */
    default void assertNotNullWithMsg(Object obj, String errMsg) {
        if (obj == null) {
            throw newExceptionWithMsg(errMsg);
        }
    }

    /**
     * 断言对象非空，如果对象为空，则抛出异常
     * @param obj 带判断对象
     * @param errMsg 自定义异常信息
     * @param args 异常信息参数（message占位符对应的参数列表）
     */
    default void assertNotNullWithMsg(Object obj, String errMsg, Object... args) {
        if (obj == null) {
            throw newExceptionWithMsg(errMsg, args);
        }
    }

    /**
     *  断言对象非空，如果对象为空，则抛出异常
     * @param obj 带判断对象
     * @param errMsg 自定义异常信息
     */
    default void assertNotNullWithMsg(Object obj, Supplier<String> errMsg) {
        if (obj == null) {
            throw newExceptionWithMsg(errMsg.get());
        }
    }

    /**
     * 断言对象obj非空。如果对象<code>obj</code>为空，则抛出异常
     * 异常信息message支持传递参数方式，避免在判断之前进行字符串拼接
     *
     * @param obj 待判断对象
     * @param errMsg 自定义的错误信息. 支持 {index} 形式的占位符, 比如: errMsg-用户[{0}]不存在, args-1001, 最后打印-用户[1001]不存在
     * @param args message占位符对应的参数列表
     */
    default void assertNotNullWithMsg(Object obj, Supplier<String> errMsg, Object... args) {
        if (obj == null) {
            throw newExceptionWithMsg(errMsg.get(), args);
        }
    }

    /**
     * 断言字符串str不为空串（长度为0）。如果字符串str为空串，则抛出异常
     *
     * @param str 待判断字符串
     */
    default void assertNotEmpty(String str) {
        if (null == str || "".equals(str.trim())) {
            throw newException();
        }
    }








}
